home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************
- * *
- * Copyright (c) 1992, 1993 Ronald Joe Record *
- * *
- * All rights reserved. No part of this program or publication may be *
- * reproduced, transmitted, transcribed, stored in a retrieval system, *
- * or translated into any language or computer language, in any form or *
- * by any means, electronic, mechanical, magnetic, optical, chemical, *
- * biological, or otherwise, without the prior written permission of: *
- * *
- * Ronald Joe Record (408) 458-3718 *
- * 212 Owen St., Santa Cruz, California 95062 USA *
- * *
- *************************************************************************/
-
- /***************************************************************************
- * *
- * Copyright (c) 1989 Hiram Clawson *
- * *
- * All rights reserved. No part of this program or publication may be *
- * reproduced, transmitted, transcribed, stored in a retrieval system, *
- * or translated into any language or computer language, in any form or *
- * by any means, electronic, mechanical, magnetic, optical, chemical, *
- * biological, or otherwise, without the prior written permission of: *
- * *
- * Hiram Clawson (408) 429-5647 *
- * P. O. Box 3178, Santa Cruz, California 95063-3178 USA *
- * *
- ***************************************************************************/
- /***************************************************************************
- * plot.c: Plot a 3D point through a window in 3D space that *
- * is the computer display screen. *
- * *
- * Written by Hiram Clawson. *
- * Ported to X11 by Ronald Joe Record. *
- ***************************************************************************/
-
- #include "globals.h"
-
- int plot( _3D_point, _2D_point ) /* returns TRUE when on screen */
- triple _3D_point;
- xy_t *_2D_point;
- {
- /*
- * Given a point in 3D space: _3D_point.x, _3D_point.y, _3D_point.z
- * and a screen center of (screen_center.x, screen_center.y)
- * (upper left is 0,0), lower right is (screen_max.x,screen_max.y)
- * (lower left is 0,0), upper right is (screen_max.x,screen_max.y)
- *
- * return plot point _2D_point->x, _2D_point->y as seen through a window
- * from the viewpoint (view_point.x, view_point.y, view_point.z)
- *
- * The window is an arbitary plane in x,y,z space defined by four points:
- * window center (window_center.x, .y, .z)
- * top middle of window (window_top.x, .y, .z)
- * right middle (window_right.x, .y, .z)
- * upper right window corner(window_upper_right.x, .y, .z)
- *
- * The viewpoint is on a perpendicular (to the window plane) line through
- * the center to the window.
- *
- * There are some global constants floating around that were set up by
- * view_point_constants concerning the window. When the window
- * is moved they are recomputed by view_point_constants.
- * They are vectors associated with the window points and the length
- * of those vectors.
- *
- * vector v_center_top, length_center_top
- * vector v_center_right length_center_right
- * vector v_view_center length_view_center
- */
-
- /* local variables */
-
- triple v_view_point;/* from view point to 3D point in question */
- double length_view_point; /* length of vector v_view_point */
- triple window; /* intersection point of window plane and */
- /* the vector v_view_point */
- double cosine_theta; /* computed cosine of angle theta */
- xy_t screen; /* computed screen x and y points */
- double cosine_alpha; /* between v_center_right and v_center_window */
- double sine_alpha; /* between v_center_right and v_center_window */
- double cosine_beta; /* between v_center_top and v_center_windos */
- double dtemp; /* for temporary double */
- triple lambda_view_point; /* from view point to 3D point */
- triple v_view_window; /* from view point to window intersect*/
- double length_view_window; /* length from view to window */
- triple v_center_window; /* from center to window intersection */
- double length_center_window_squared;
- double length_center_window; /* length from center to intersection */
-
- /* code starts here **********************************************/
-
- /* assume point is not in view */
-
- _2D_point->x = 0;
- _2D_point->y = 0;
-
- /* compute vector v_view_point: view point to 3D point in question */
-
- VECTORIZE( v_view_point, view_point, _3D_point );
-
- /*
- * length of vector v_view_point (check point in question is not EXACTLY
- * at the same place as the view point otherwise sqrt will give error)
- */
-
- if ( POINTS_NOT_EQUAL( view_point, _3D_point ) )
- {
- length_view_point = VECTOR_LENGTH( v_view_point );
- }
- else
- {
- return( FALSE );
- }
-
- /*
- * if length is not more than that from view point to window, ignore
- * the point, and exit here because point is not in view
- */
-
- if( length_view_point <= length_view_center )
- {
- return( FALSE );
- }
-
- /*
- * compute angle between vector v_view_center and v_view_point
- * for angles -90 to +90 cosine_theta is between 0 and 1
- * for angles greater than 90 degrees, cosine_theta is negative
- */
-
- if ( (cosine_theta = ( DOT_PRODUCT( v_view_center, v_view_point ) )/
- (length_view_point * length_view_center) )
- <= cosine_half_field_of_view )
- {
- /* cosine_theta is less than half of the field
- of view, which means the point is not visible on the screen */
- return(FALSE);
- }
-
- /*
- * Point is on the screen, plot it.
- *
- * compute length along vector v_view_point to its intersection with the
- * plane of the window
- */
-
- length_view_window = length_view_center / cosine_theta;
-
- /* unit vector on vector v_view_point is */
-
- UNIT_VECTOR( lambda_view_point, v_view_point, length_view_point );
-
- /* vector view point to the window along the vector v_view_point is */
-
- VECTOR_X_SCALAR( v_view_window, lambda_view_point, length_view_window );
-
- /* window point is view point plus vector v_view_window */
-
- POINT_PLUS_VECTOR( window, view_point, v_view_window );
-
- /* now to find which quadrant on the screen this point is at */
-
- /* vector from center of window to the window point is */
-
- VECTORIZE( v_center_window, window_center, window );
-
- /* length squared of v_center_window */
-
- length_center_window_squared = (v_center_window.x * v_center_window.x)+
- (v_center_window.y * v_center_window.y)+
- (v_center_window.z * v_center_window.z);
-
- /* compute angle between vectors v_center_window and v_center_right */
-
- if( length_center_window_squared > 0.0 )
- {
- length_center_window = sqrt( length_center_window_squared );
- cosine_alpha=((DOT_PRODUCT(v_center_window, v_center_right ) ) /
- (length_center_right * length_center_window) );
- cosine_beta=((DOT_PRODUCT( v_center_window, v_center_top ) ) /
- (length_center_top * length_center_window) );
- }
- else /* we have a point directly at screen center */
- {
- _2D_point->x = screen_center.x;
- _2D_point->y = screen_center.y;
- return( TRUE );
- }
-
- /*
- * the two angles alpha and beta are computed to help find the quadrant.
- * for quadrant x > 0, y > 0 cos_alpha > 0 and cos_beta > 0
- * for quadrant x < 0, y > 0 cos_alpha < 0 and cos_beta > 0
- * for quadrant x < 0, y < 0 cos_alpha < 0 and cos_beta < 0
- * for quadrant x > 0, y < 0 cos_alpha > 0 and cos_beta < 0
- *
- * now have an angle and a length on the screen, plot the point
- * get the sine from the cosine. ( sin*sin + cos*cos ) = 1
- * sin = sqrt( 1 - (cos*cos) )
- */
-
- if ( (dtemp=(cosine_alpha * cosine_alpha)) >= 1.0 )
- sine_alpha = 0.0; /* overflow protection */
- else /* sometimes cos*cos is slightly over 1.0 by round off error */
- sine_alpha = sqrt( 1.0 - dtemp );
-
- if ( cosine_beta < 0.0 ) /* quadrant is where y < 0 */
- sine_alpha = - sine_alpha;
-
- /*
- * Here as calculated,
- * screen.x and .y are the x and y components of the vector v_center_window
- * in the screen pixel units based on a coordinate system that is
- * a normal x positive to right, y positive up.
- */
- screen.x = length_center_window * cosine_alpha / _3D_units_per_ypixel;
- screen.y = length_center_window * sine_alpha / _3D_units_per_ypixel;
-
- /*
- * convert to coordinate system of the video screen where y is positive
- * down.
- * (needed when coord system is (0,0) upper left, (maxx, maxy) lower right)
- * (NOTE: commented out for CGI)
- screen.x = (screen.x * aspect_ratio) + screen_center.x;
- screen.y = screen_center.y - screen.y;
- *
- * In the case of (0,0) lower left and (maxx, maxy) upper right, just
- * adjust for aspect ratio. (This is CGI.)
- */
- screen.x = screen.x + screen_center.x;
- screen.y = screen_center.y + screen.y;
-
- /* final limit checks, just in case. */
-
- if ( (screen.x < 0) || (screen.x > screen_max.x) ||
- (screen.y < 0) || (screen.y > screen_max.y) )
- {
- return(FALSE); /* something went wrong */
- }
- else
- {
- _2D_point->x = screen.x;
- _2D_point->y = screen.y;
- return( TRUE ); /* plot is OK */
- }
-
- return( FALSE ); /* should NEVER get to here */
-
- } /* end of plot */
-